﻿using System;
using System.Collections.Generic;
using System.Text;
using StarBotDotNet;
using StarBotDotNet.BuildStateCheckers;

namespace StarBotDotNet
{
    public abstract class StateCheckerAbstract
    {


        static List<StateCheckerAbstract> checkers;

        static StateCheckerAbstract()
        {
            checkers = new List<StateCheckerAbstract>();
            AddStateChecker(new StateCheckerAquiredProduced());
            AddStateChecker(new StateCheckerAllocateResources());
            AddStateChecker(new StateCheckerBuild());
            AddStateChecker(new StateCheckerFinished());
        }

        private static void AddStateChecker(StateCheckerAbstract checker)
        {
            checkers.Add( checker);
        }

        public static IEnumerable<StateCheckerAbstract> EnumerateCheckers(BuildStateEnum state, BuildStateEnum stateTo)
        {
            foreach (StateCheckerAbstract checker in checkers)
            {
                if (checker.StateFrom == state)
                {
                    if ((checker.StateTo == stateTo) || (state == stateTo))
                    {
                        yield return checker;
                    }
                }
            }
        }

        protected abstract bool CanEnterThisState(IBuildingParty buildingParty, BuildTarget target, ProxyBot bot, UnitDictionary currentUnits, int currentTime);
        protected abstract bool CanTryToMoveToThisState(IBuildingParty buildingParty, BuildTarget target, ProxyBot bot, UnitDictionary currentUnits, int currentTime);
        /// <summary>
        /// Begins the move to a new state
        /// For example allocates resources or orders prerequizite units
        /// </summary>
        /// <param name="target"></param>
        /// <param name="thisState"></param>
        /// <param name="bot"></param>
        /// <param name="currentUnits"></param>
        /// <param name="currentTime"></param>
        protected abstract void InitiateMovingToThisState(IBuildingParty buildingParty, BuildTarget target, ProxyBot bot, UnitDictionary currentUnits, int currentTime);
        /// <summary>
        /// Ensures prerequizites for starting to move into new state are met
        /// Can be called many times,
        /// for example when a worker reaches building site and it is taken
        /// </summary>
        /// <param name="buildingParty"></param>
        /// <param name="target"></param>
        /// <param name="thisState"></param>
        /// <param name="bot"></param>
        /// <param name="currentUnits"></param>
        /// <param name="currentTime"></param>
        protected abstract void PrepareInitiationOfMovingToThisState(IBuildingParty buildingParty, BuildTarget target, ProxyBot bot, UnitDictionary currentUnits, int currentTime);


        public abstract BuildStateEnum StateFrom
        {
            get;
        }

        public abstract BuildStateEnum StateTo
        {
            get;
        }

        protected virtual void AfterMovingToState(ProxyBot bot, IBuildingParty buildingParty, BuildTarget target)
        {

        }

        public void TryToMoveToNextState(IBuildingParty buildingParty, BuildTarget target, ProxyBot bot, UnitDictionary currentUnits, int currentTime)
        {
            if (!target.IsMovingToNextState())
            {
                if (CanTryToMoveToThisState(buildingParty,target, bot, currentUnits, currentTime))
                {
                    target.SetIsMovingToNextState(StateTo);
                    InitiateMovingToThisState(buildingParty, target, bot, currentUnits, currentTime);
                }
                else
                {
                    PrepareInitiationOfMovingToThisState( buildingParty, target, bot, currentUnits, currentTime);
                }

            }
            else
            {
                if (CanEnterThisState( buildingParty,target,bot, currentUnits, currentTime))
                {
                    target.MoveToNextState();
                    AfterMovingToState( bot,buildingParty, target);
                }
            }
        }



    }
}
